import fetch from 'node-fetch';

interface RealtimeStockData {
  currentPrice: number;
  openPrice: number;
  closePrice: number;
  highPrice: number;
  lowPrice: number;
  volume: bigint;
  turnover: number;
  changeAmount: number;
  changePercent: number;
  timestamp: Date; // 添加时间戳
}

export class SinaStockAPI {
  private baseURL = 'https://hq.sinajs.cn';
  private maxRetries = 3; // 最大重试次数
  private retryDelay = 1000; // 重试延迟(毫秒)
  private requestDelay = 500; // 请求间隔(毫秒)
  private failedRequestsCount = 0; // 失败请求计数
  private maxFailedRequests = 10; // 最大失败请求数，超过则暂停服务
  private serviceUnavailableUntil: Date | null = null; // 服务暂停截止时间
  private serviceResumeDelay = 300000; // 服务恢复延迟(5分钟)

  // 市场代码映射
  private marketPrefixes = {
    'SH': 'sh',    // 上海A股
    'SZ': 'sz',    // 深圳A股
    'HK': 'hk',    // 港股
    'US': 'gb',    // 美股 (使用gb前缀)
    'UK': 'lse',   // 英股
    'NEEQ': 'neeq' // 新三板
  };

  constructor(config?: {
    maxRetries?: number;
    retryDelay?: number;
    requestDelay?: number;
    maxFailedRequests?: number;
    serviceResumeDelay?: number;
  }) {
    if (config) {
      this.maxRetries = config.maxRetries || this.maxRetries;
      this.retryDelay = config.retryDelay || this.retryDelay;
      this.requestDelay = config.requestDelay || this.requestDelay;
      this.maxFailedRequests = config.maxFailedRequests || this.maxFailedRequests;
      this.serviceResumeDelay = config.serviceResumeDelay || this.serviceResumeDelay;
    }
  }

  /**
   * 检查服务是否可用
   */
  private isServiceAvailable(): boolean {
    if (this.serviceUnavailableUntil && new Date() < this.serviceUnavailableUntil) {
      console.warn(`⏰ 新浪API服务暂停中，恢复时间: ${this.serviceUnavailableUntil.toLocaleString()}`);
      return false;
    }
    
    // 如果服务恢复时间已过，重置计数器
    if (this.serviceUnavailableUntil && new Date() >= this.serviceUnavailableUntil) {
      this.serviceUnavailableUntil = null;
      this.failedRequestsCount = 0;
      console.log('✅ 新浪API服务已恢复');
    }
    
    return true;
  }

  /**
   * 记录失败请求
   */
  private recordFailedRequest(): void {
    this.failedRequestsCount++;
    console.warn(`⚠️ 失败请求计数: ${this.failedRequestsCount}/${this.maxFailedRequests}`);
    
    if (this.failedRequestsCount >= this.maxFailedRequests) {
      this.serviceUnavailableUntil = new Date(Date.now() + this.serviceResumeDelay);
      console.error(`❌ 新浪API失败次数过多，暂停服务到: ${this.serviceUnavailableUntil.toLocaleString()}`);
    }
  }

  /**
   * 重置失败计数（成功请求时调用）
   */
  private resetFailedCount(): void {
    if (this.failedRequestsCount > 0) {
      console.log(`✅ 请求成功，重置失败计数 (之前: ${this.failedRequestsCount})`);
      this.failedRequestsCount = 0;
    }
  }

  /**
   * 获取股票实时数据
   */
  async getRealtimeData(marketCode: string, stockCode: string): Promise<RealtimeStockData | null> {
    // 检查服务是否可用
    if (!this.isServiceAvailable()) {
      return null;
    }

    const prefix = this.marketPrefixes[marketCode as keyof typeof this.marketPrefixes];
    if (!prefix) {
      throw new Error(`不支持的市场: ${marketCode}`);
    }

    // 美股需要小写代码和下划线
    let symbol;
    if (marketCode === 'US') {
      symbol = `${prefix}_${stockCode.toLowerCase()}`;
    } else {
      symbol = `${prefix}${stockCode}`;
    }
    const url = `${this.baseURL}/list=${symbol}`;

    console.log(`正在获取股票数据: ${url}`);
    
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        await this.delay(this.requestDelay); // 请求间隔控制
        
        const response = await fetch(url, {
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Referer': 'https://finance.sina.com.cn'
          }
        });

        if (!response.ok) {
          throw new Error(`HTTP Error: ${response.status}`);
        }

        const text = await response.text();
        
        // 检查是否返回了"Kinsoku jikou desu!"（被禁用的响应）
        if (text.includes('Kinsoku jikou desu!')) {
          console.warn('新浪API返回禁用响应，可能需要使用其他方法');
          this.recordFailedRequest(); // 记录失败请求
          return null;
        }

        const data = this.parseRealtimeData(text, marketCode);
        if (data) {
          data.timestamp = new Date(); // 添加时间戳
          this.resetFailedCount(); // 重置失败计数
        }
        
        return data;
      } catch (error: any) {
        console.error(`获取实时数据失败 ${marketCode}:${stockCode} (尝试 ${attempt}/${this.maxRetries})`, error.message);
        
        if (attempt === this.maxRetries) {
          this.recordFailedRequest(); // 记录失败请求
          return null;
        }
        
        await this.delay(this.retryDelay * attempt); // 指数退避重试
      }
    }
    
    return null;
  }

  /**
   * 批量获取股票实时数据
   */
  async getBatchRealtimeData(stocks: Array<{ marketCode: string, stockCode: string }>): Promise<Array<{ stockCode: string, data: RealtimeStockData | null }>> {
    // 检查服务是否可用
    if (!this.isServiceAvailable()) {
      return stocks.map(stock => ({ stockCode: stock.stockCode, data: null }));
    }

    const validStocks = stocks.filter(stock => {
      const prefix = this.marketPrefixes[stock.marketCode as keyof typeof this.marketPrefixes];
      return !!prefix;
    });

    if (validStocks.length === 0) return stocks.map(stock => ({ stockCode: stock.stockCode, data: null }));

    // 分批处理，避免单次请求过多股票
    const batchSize = 20;
    const results: Array<{ stockCode: string, data: RealtimeStockData | null }> = [];

    for (let i = 0; i < validStocks.length; i += batchSize) {
      const batch = validStocks.slice(i, i + batchSize);
      const symbols = batch.map(stock => {
        const prefix = this.marketPrefixes[stock.marketCode as keyof typeof this.marketPrefixes];
        // 美股需要小写代码和下划线
        if (stock.marketCode === 'US') {
          return `${prefix}_${stock.stockCode.toLowerCase()}`;
        } else {
          return `${prefix}${stock.stockCode}`;
        }
      });

      try {
        await this.delay(this.requestDelay); // 请求间隔控制
        
        const url = `${this.baseURL}/list=${symbols.join(',')}`;
        
        const response = await fetch(url, {
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Referer': 'https://finance.sina.com.cn'
          }
        });

        if (!response.ok) {
          throw new Error(`HTTP Error: ${response.status}`);
        }

        const text = await response.text();
        const lines = text.split('\n').filter(line => line.trim());

        let batchSuccessCount = 0;
        batch.forEach((stock, index) => {
          const data = lines[index] ? this.parseRealtimeData(lines[index], stock.marketCode) : null;
          if (data) {
            data.timestamp = new Date(); // 添加时间戳
            batchSuccessCount++;
          }
          results.push({
            stockCode: stock.stockCode,
            data
          });
        });

        // 如果批次中有成功的数据，重置失败计数
        if (batchSuccessCount > 0) {
          this.resetFailedCount();
        }
      } catch (error: any) {
        console.error('批量获取实时数据失败:', error.message);
        this.recordFailedRequest(); // 记录失败请求
        batch.forEach(stock => {
          results.push({
            stockCode: stock.stockCode,
            data: null
          });
        });
      }
    }

    // 确保返回结果与输入顺序一致
    return stocks.map(stock => {
      const result = results.find(r => r.stockCode === stock.stockCode);
      return result || { stockCode: stock.stockCode, data: null };
    });
  }

  /**
   * 解析新浪API返回的实时数据
   */
  private parseRealtimeData(dataString: string, marketCode: string): RealtimeStockData | null {
    try {
      // 提取双引号内的数据
      const match = dataString.match(/"([^"]*)"/);
      if (!match) return null;

      const data = match[1].split(',');
      
      // 根据市场类型解析数据格式
      if (marketCode === 'SH' || marketCode === 'SZ') {
        // A股数据格式
        return this.parseAStockData(data);
      } else if (marketCode === 'HK') {
        // 港股数据格式
        return this.parseHKStockData(data);
      } else if (marketCode === 'US') {
        // 美股数据格式
        return this.parseUSStockData(data);
      } else {
        // 其他市场使用通用格式
        return this.parseGenericStockData(data);
      }
    } catch (error: any) {
      console.error('解析股票数据失败:', error.message);
      return null;
    }
  }

  /**
   * 解析A股数据格式
   */
  private parseAStockData(data: string[]): RealtimeStockData | null {
    if (data.length < 32) return null;

    const openPrice = parseFloat(data[1]) || 0;
    const closePrice = parseFloat(data[2]) || 0;
    const currentPrice = parseFloat(data[3]) || 0;
    const highPrice = parseFloat(data[4]) || 0;
    const lowPrice = parseFloat(data[5]) || 0;
    const volume = BigInt(parseInt(data[8]) || 0);
    const turnover = parseFloat(data[9]) || 0;

    return {
      currentPrice,
      openPrice,
      closePrice,
      highPrice,
      lowPrice,
      volume,
      turnover,
      changeAmount: currentPrice - closePrice,
      changePercent: closePrice > 0 ? ((currentPrice - closePrice) / closePrice) * 100 : 0,
      timestamp: new Date()
    };
  }

  /**
   * 解析港股数据格式
   * 数据格式：TENCENT,腾讯控股,605.500,605.500,619.000,605.000,617.500,12.000,1.982,617.00000,617.50000,12199067786,19919381,0.000,0.000,621.000,361.643,2025/09/08,15:52
   * 索引：0=英文名,1=中文名,2=开盘价,3=昨收价,4=最高价,5=最低价,6=现价,7=涨跌额,8=涨跌幅,9=买一价,10=卖一价,11=成交量,12=成交额
   */
  private parseHKStockData(data: string[]): RealtimeStockData | null {
    if (data.length < 13) return null;

    const currentPrice = parseFloat(data[6]) || 0;  // 现价
    const closePrice = parseFloat(data[3]) || 0;    // 昨收价
    const openPrice = parseFloat(data[2]) || 0;     // 开盘价
    const highPrice = parseFloat(data[4]) || 0;     // 最高价
    const lowPrice = parseFloat(data[5]) || 0;      // 最低价
    const volume = BigInt(parseInt(data[11]) || 0); // 成交量
    const turnover = parseFloat(data[12]) || 0;     // 成交额

    return {
      currentPrice,
      openPrice,
      closePrice,
      highPrice,
      lowPrice,
      volume,
      turnover,
      changeAmount: currentPrice - closePrice,
      changePercent: closePrice > 0 ? ((currentPrice - closePrice) / closePrice) * 100 : 0,
      timestamp: new Date()
    };
  }

  /**
   * 解析美股数据格式
   * 数据格式：苹果,239.6900,-0.04,2025-09-08 16:12:50,-0.0900,239.9950,241.3200,238.4901,259.3300,168.6900,54870397,44971125,3557093079100,6.61,36.260000,...
   * 索引：0=中文名,1=现价,2=涨跌额,3=时间,4=涨跌额,5=昨收价,6=最高价,7=最低价,8=52周最高,9=52周最低,10=成交量,11=...
   */
  private parseUSStockData(data: string[]): RealtimeStockData | null {
    if (data.length < 11) return null;

    const currentPrice = parseFloat(data[1]) || 0;  // 现价
    const closePrice = parseFloat(data[5]) || 0;    // 昨收价
    const highPrice = parseFloat(data[6]) || 0;     // 最高价
    const lowPrice = parseFloat(data[7]) || 0;      // 最低价
    const volume = BigInt(parseInt(data[10]) || 0); // 成交量
    
    // 开盘价不在标准位置，使用昨收价或现价作为估算
    const openPrice = closePrice || currentPrice;

    return {
      currentPrice,
      openPrice,
      closePrice,
      highPrice,
      lowPrice,
      volume,
      turnover: 0, // 美股数据中没有成交额字段
      changeAmount: currentPrice - closePrice,
      changePercent: closePrice > 0 ? ((currentPrice - closePrice) / closePrice) * 100 : 0,
      timestamp: new Date()
    };
  }

  /**
   * 解析通用股票数据格式
   */
  private parseGenericStockData(data: string[]): RealtimeStockData | null {
    if (data.length < 5) return null;

    const currentPrice = parseFloat(data[1]) || 0;
    const openPrice = parseFloat(data[2]) || 0;
    const highPrice = parseFloat(data[3]) || 0;
    const lowPrice = parseFloat(data[4]) || 0;
    const closePrice = parseFloat(data[5]) || currentPrice; // 如果没有昨收价，使用现价

    return {
      currentPrice,
      openPrice,
      closePrice,
      highPrice,
      lowPrice,
      volume: BigInt(0),
      turnover: 0,
      changeAmount: currentPrice - closePrice,
      changePercent: closePrice > 0 ? ((currentPrice - closePrice) / closePrice) * 100 : 0,
      timestamp: new Date()
    };
  }

  /**
   * 测试API连接性
   */
  async testConnection(): Promise<boolean> {
    try {
      await this.delay(this.requestDelay); // 请求间隔控制
      const response = await fetch(`${this.baseURL}/list=sh000001`);
      const isConnected = response.ok;
      
      if (isConnected) {
        this.resetFailedCount(); // 连接成功时重置失败计数
      } else {
        this.recordFailedRequest(); // 连接失败时记录
      }
      
      return isConnected;
    } catch (error: any) {
      console.error('测试连接失败:', error.message);
      this.recordFailedRequest(); // 记录失败请求
      return false;
    }
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}
